﻿using SlimDX;
using SlimDX.Direct3D10;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ColladaLoader;


using System.Runtime.InteropServices;

namespace SCS.GFX {
  public class ColladaMeshObject : Object {

    ColladaModel      FModel;
    List<MeshObject>  FMesh = new List<MeshObject>();


    //Temporary vars to draw & debug bone structure
    public SlimDX.Direct3D10.Buffer FVertexBuffer;
    public SlimDX.Direct3D10.Buffer FIndexBuffer;
    public int FVerticeCount;
    List<PositionColored> FBoneVertices = new List<PositionColored>();
    public InputLayout FLayout;
    public Effect FEffect;
    public EffectPass FPass;
    public EffectTechnique FTechnique;


/*            //Load the effect (shader) from a file
            FEffect = Effect.FromFile(dev, System.IO.Directory.GetCurrentDirectory() + "\\Effects\\PositionColored.fx", "fx_4_0", ShaderFlags.None, EffectFlags.None, null, null);
            //Get the first technique
            FTechnique = FEffect.GetTechniqueByIndex(0);
            //Get the first pass
            FPass = FTechnique.GetPassByIndex(0);


            FEffectVariable = FEffect.GetVariableByName("ViewProjection");
            FEffectViewProjectionMatrix = FEffectVariable.AsMatrix();

            FEffectVariable = FEffect.GetVariableByName("World");
            FEffectWorldMatrix = FEffectVariable.AsMatrix();
*/


    public ColladaMeshObject(string modelName, Vector3 pos) 
    {
        FEffect = Effect.FromFile(Renderer.Device, "..\\..\\..\\..\\Effects\\PositionColored.fx", "fx_4_0", ShaderFlags.None, EffectFlags.None, null, null);
        FTechnique = FEffect.GetTechniqueByIndex(0);
        //Get the first pass
        FPass = FTechnique.GetPassByIndex(0);

      FLayout = new InputLayout(Renderer.Device, PositionColored.InputElements, FPass.Description.Signature);

      FModel = new ColladaModel(modelName);
  
      foreach (MeshContainer m in FModel.meshes) {
        foreach (SceneNode s in FModel.SceneNodes) {
          if (m.Name == s.GeometryLink) {
            m.position = pos;
            m.objectMatrix = s.World;

          }
        }
        if (m.textures.Count > 0) //are there textures on the mesh ?
          FMesh.Add(new TexturedMeshObject(m));
        else
          FMesh.Add(new ColoredMeshObject(m));
      }

      FBoneVertices.Add(new PositionColored(new Vector3(0, 0, 0), new Vector4(1.0f,0.0f,0.0f,0.0f)));

      foreach (Bone b in FModel.bones) {
          FBoneVertices.Add(new PositionColored(new Vector3(b.finalMatrix.M41, b.finalMatrix.M42, b.finalMatrix.M43), new Vector4(1.0f, 0.0f, 0.0f, 0.0f)));
      }
      
      if (FBoneVertices.Count > 0)
        LoadVertexBuffer(null);
    }

    public void LoadVertexBuffer(List<SkinnedTangentVertex> verts) {

      FVerticeCount = FBoneVertices.Count;

      //Construct vertex buffer for drawing
      BufferDescription bufferDescription = new BufferDescription();
      bufferDescription.BindFlags = BindFlags.VertexBuffer;
      bufferDescription.CpuAccessFlags = CpuAccessFlags.None;
      bufferDescription.OptionFlags = ResourceOptionFlags.None;
      bufferDescription.SizeInBytes = FVerticeCount * PositionColored.SizeInBytes;
      bufferDescription.Usage = ResourceUsage.Default;

      DataStream stream = new DataStream(FVerticeCount * PositionColored.SizeInBytes, true, true);
      stream.Position = 0;
      foreach (PositionColored i in FBoneVertices) {
        stream.Write(new Vector3(i.X, i.Y,i.Z));
        stream.Write(new Vector4(1.0f,0.0f,0.0f,0.0f));
      }
      stream.Position = 0;
      FVertexBuffer = new SlimDX.Direct3D10.Buffer(Renderer.Device, stream, bufferDescription);
      stream.Close();
    }

    public void SetPosition(Vector3 pos)
    {
        foreach (MeshObject o in FMesh)
        {
            o.SetPosition(pos);
        }
    }

    public void Render(RenderInfo aInfo) {
//      base.Render(aInfo);

      //Render all submeshes
      foreach (MeshObject o in FMesh) {
        o.Render(aInfo);
      }
/*bones crap
      Renderer.Device.InputAssembler.SetInputLayout(FLayout);
      Renderer.Device.InputAssembler.SetPrimitiveTopology(PrimitiveTopology.LineList);
      Renderer.Device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(FVertexBuffer, PositionColored.SizeInBytes, 0));

      FPass.Apply();
      Renderer.Device.Draw(FVerticeCount, 0);
 * */
    }

    public void Dispose() {

      if (FModel != null) FModel.Dispose();
      
      foreach (MeshObject o in FMesh) {
        if (o!=null) o.Dispose();
      }
    }
  }
}
